package org.com.yz.dubbo.web.core;


import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.com.yz.common.constant.PayConstant;
import org.com.yz.common.util.*;
import org.com.yz.dal.dao.model.MchAccnt;
import org.com.yz.dal.dao.model.MchsubQueryEs;
import org.com.yz.dal.dao.model.MchSubInfo;
import org.com.yz.dal.dao.model.DispatchInfo;
import org.com.yz.dal.dao.model.*;
import org.com.yz.dubbo.web.service.CheckMchAccntService;
import org.com.yz.dubbo.web.service.CheckWithDrawService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 接口校验参数AOP
 * * 考虑到参数校验有些需要连接数据库查询，本着参数校验在进方法之前
 * * 所以AOP放在了web包，没有放在common里
 *
 * author fanjj
 * date 2018.7.20
 */

@Aspect
@Component
public class ParameterAop {
    private final MyLog _log = MyLog.getLog(ParameterAop.class);

    @Autowired
    private CheckMchAccntService checkMchAccntService;

    @Autowired
    private CheckWithDrawService checkWithDrawService;
    @Pointcut(value = "@annotation(org.com.yz.common.annotion.Parameter)")
    public void parameterVerification() {
    }


    /**
     * 参数校验AOP，包括参数校验，签名校验，分接口的自定义校验
     * **
     *
     * param point
     * return
     * throws Throwable
     */
    @Around("parameterVerification()")
    public Object doPermission(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        JSONObject jsonObject = new JSONObject();
        String sign = "", data, result;
        try {
            //校验参数
            data = args[0].toString();
            sign = args[1].toString();
            _log.info("接收到的报文为：\n data:" + XmlFormatter.formatJson(data) + "\n sign:" + XmlFormatter.formatJson(sign));
            result = StringEscapeUtils.unescapeJava(data);
            jsonObject = JSONObject.parseObject(result);
            Map map = validateParams(jsonObject, sign, result);//校验公共参数
            String code = map.get("code").toString();
            if (ToolUtil.isNotEmpty(code) && !"0000".equals(code)) {//如果code不是0000，则表示参数校验失败
                String message = map.get("message").toString();
                _log.info("参数校验不通过:{" + message + "}");
                return ClassRefUtil.createErrorRetData(jsonObject, sign, code, message);
            }
            _log.info("参数校验通过");
            //校验签名
            String token = CacheUtil.me().getMd5Token(jsonObject.getString("mch_no"));
            boolean verifyFlag = XXPayUtil.verifySign(sign, token, data, jsonObject.getString("timestamp"));//此时data带斜杠，生成的签名也是data带斜杠的，未知：请求的签名是否带斜杠
            if (!verifyFlag) {
                _log.info("签名校验不通过:{" + PayConstant.RETURN_DEPOSIT_SIGN_FAILS + "}");
                return ClassRefUtil.createErrorRetData(jsonObject, sign, PayConstant.RETURN_DEPOSIT_SIGN_FAIL, PayConstant.RETURN_DEPOSIT_SIGN_FAILS);
            }
            _log.info("签名校验通过");
            //如果都通过，就继续处理controller的逻辑（仍需校验每个接口都不同的bizContent）
            return point.proceed();
        } catch (Exception e) {
            _log.info("系统校验参数出错" + ToolUtil.getExceptionMsg(e));
            return ClassRefUtil.createErrorRetData(jsonObject, sign, PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
    }


    /**
     * 验证公共参数
     *
     * param params
     * return
     */
    private Map validateParams(JSONObject params, String sign, String data) {
        // 支付参数
        String mchNo = params.getString("mch_no");                // 商户号
        String outTransNo = params.getString("out_trans_no");     // 请求追踪号
        String bizType = params.getString("biz_type");     // 交易类型
        String bizContent = params.getString("biz_content");    // 请求的业务数据
        String signType = params.getString("sign_type");        // 签名加密方式
        String timestamp = params.getString("timestamp");            // 请求时间
        // 签名信息
        if (StringUtils.isEmpty(sign)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{签名}");
        }
        //商户号
        if (StringUtils.isEmpty(mchNo)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{商户号}");
        }
        //请求追踪号
        if (StringUtils.isEmpty(outTransNo)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{请求追踪号}");
        }
        //交易类型
        if (StringUtils.isEmpty(bizType)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{交易类型}");
        }
        //请求业务数据
        if (StringUtils.isEmpty(bizContent)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{请求业务数据}");
        }
        //签名加密方式
        if (StringUtils.isEmpty(signType)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{签名加密方式}");
        }
        //请求时间
        if (StringUtils.isEmpty(timestamp)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{请求时间}");
        }
        // 商户号不存在
        MchAccnt mchAccnt = new MchAccnt();
        mchAccnt.setMchNo(mchNo);
        if (!checkMchAccntService.getByMchId(mchAccnt)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MCHNO_NULL, PayConstant.RETURN_DEPOSIT_MCHNO_NULLS);
        }
        //请求追踪号已存在
       /*if(checkTransService.getTransNo(outTransNo,mchNo)){
            return createMap(PayConstant.RETURN_DEPOSIT_ONT_ONLYS,PayConstant.RETURN_DEPOSIT_ONT_ONLY);
        }*/
        //自定义校验
        return checkDiy(bizType, data);
    }


    //组装参数校验map
    private Map createMap(String code, String message) {
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("code", code);
        resultMap.put("message", message);
        return resultMap;
    }


    //自定义校验
    private Map checkDiy(String bizeType, String data) {
        switch (bizeType) {
            case PayConstant.MCHSUB_CREATE://开设子商户账户
                return checkCreate(data);
            case PayConstant.MCHSUB_BIND_BANKCARD://子商户账户绑定银行卡
                return checkBindCard(data);
            case PayConstant.MCHSUB_UNBIND_BANKCARD://子商户账户解绑银行卡
                return checkUnBindCard(data);
            case PayConstant.MCHSUB_BATCH_CREATE://批量开设子商户
                return checkBatchCreate(data);
            case PayConstant.MCHSUB_QUERY://子商户账户查询
                return checkQuery(data);
            case PayConstant.MCHSUB_DISPATCH://商户分账
                return checkDispatch(data);
            case PayConstant.MCHSUB_PAY_DISPATCH: //商户支付记账
                return checkPayDispatch(data);
            case PayConstant.MCHSUB_REFUND_DISPATCH: //商户退款记账
                return checkRefundDispatch(data);
            case PayConstant.MCHSUB_OTHER_DISPATCH: //商户非支付退款记账
                return checkOtherDispatch(data);
            case PayConstant.MCHSUB_WITHDRAW://账户提现
                return checkWithDraw(data);
            case PayConstant.MCHSUB_WITHDRAW_QUERY://账户提现查询
                return checkWithDrawQuery(data);
            case PayConstant.MCHSUB_BALANCE_QUERY://余额查询
                return checkBalanceQuery(data);
            case PayConstant.MCHSUB_NOSTRO_ACCOUNT://往账
                return checkNostro(data);
        }
        return createMap("0000", "");
    }


    /**
     * 开设子商户账户校验
     */
    private Map checkCreate(String data) {
        //校验bizContent里的参数
        MchSubInfo req = JSONObject.parseObject(data, MchSubInfo.class);
        String outMchAccntno = req.getBizContent().getOutMchAccntNo();//外部子商户号
        String linkName = req.getBizContent().getLinkName();//联系人
        String mchAccntName = req.getBizContent().getMchAccntName();//子商户名称
        String linkPhone = req.getBizContent().getLinkPhone();//联系电话
        if (ToolUtil.isEmpty(outMchAccntno)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{外部子商户号}");
        }
        if (outMchAccntno.length() > 100) {
            return createMap(PayConstant.RETURN_DEPOSIT_OUTNO_ERROR, PayConstant.RETURN_DEPOSIT_OUTNO_ERRORS);
        }
        if (ToolUtil.isEmpty(linkName)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{联系人}");
        }
        if (ToolUtil.isEmpty(mchAccntName)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{子商户名称}");
        }
        if (ToolUtil.isEmpty(linkPhone)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{联系电话}");
        }
        return createMap("0000", "");
    }

    /**
     * 子商户账户绑定银行卡校验
     */
    private Map checkBindCard(String data) {
        try {
            MchsubBindBankCard mchsubBindBankCard = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), MchsubBindBankCard.class);  //转换为对象
            //效验参数
            String checkBankMsg = checkBandCard(mchsubBindBankCard.getBizContent());
            String cardAccntType = mchsubBindBankCard.getBizContent().getCardAccntType();
            if (StringUtils.isNotEmpty(checkBankMsg)) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, checkBankMsg);
            }
            MchAccnt mchAccnt2 = new MchAccnt();
            mchAccnt2.setMchAccntNo(mchsubBindBankCard.getBizContent().getMchAccntNo());
            mchAccnt2.setMchNo(mchsubBindBankCard.getBizContent().getMchNo());

            MchAccnt accnt = checkMchAccntService.selectAccntInfo(mchAccnt2);
            if ("1".equals(cardAccntType)) {//对私
                if (!accnt.getLinkName().equals(mchsubBindBankCard.getBizContent().getUserName())) {
                    return createMap(PayConstant.RETURN_DEPOSIT_LINKNAME_ERROR, PayConstant.RETURN_DEPOSIT_LINKNAME_ERRORS);
                }
            }
            //账户号必须是已存在的
            MchAccnt mchAccnt = new MchAccnt();
            mchAccnt.setMchAccntNo(mchsubBindBankCard.getBizContent().getMchAccntNo());
            mchAccnt.setMchNo(mchsubBindBankCard.getMchNo());
            if (!checkMchAccntService.getByMchId(mchAccnt)) {
                return createMap(PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULL, PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULLS);
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }

    /**
     * 子商户账户解绑银行卡校验
     */
    private Map checkUnBindCard(String data) {
        try {
            MchsubBindBankCard mchsubBindBankCard = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), MchsubBindBankCard.class);  //转换为对象
            //效验参数
            if (StringUtils.isEmpty(mchsubBindBankCard.getBizContent().getMchAccntNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{子商户账户号}");
            }
            //账户号必须是已存在的
            MchAccnt mchAccnt = new MchAccnt();
            mchAccnt.setMchAccntNo(mchsubBindBankCard.getBizContent().getMchAccntNo());
            mchAccnt.setMchNo(mchsubBindBankCard.getMchNo());
            if (!checkMchAccntService.getByMchId(mchAccnt)) {
                return createMap(PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULL, PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULLS);
            }
            if (StringUtils.isEmpty(mchsubBindBankCard.getBizContent().getCardNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{卡号}");
            }
            BankCard bankCard = checkWithDrawService.checkNostro(mchsubBindBankCard.getBizContent().getCardNo(), mchsubBindBankCard.getBizContent().getMchAccntNo(), mchsubBindBankCard.getMchNo(), "1");
            if (ToolUtil.isEmpty(bankCard)) {//卡号需已存在
                return createMap(PayConstant.RETURN_DEPOSIT_CARD_NULL, PayConstant.RETURN_DEPOSIT_CARD_NULLS);
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }

    /**
     * 批量开设子商户校验
     */
    private Map checkBatchCreate(String data) {
        try {
            BatchCreateMchSubEs subEs = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), BatchCreateMchSubEs.class);
            List<MchAccnt> mchAccntList = subEs.getBizContent().getMchAccnts();
            if (mchAccntList.size() > 100) {
                return createMap(PayConstant.RETURN_DEPOSIT_BACTH_CREATE_ACCNT_NUM_INVALID, PayConstant.RETURN_DEPOSIT_BACTH_CREATE_ACCNT_NUM_INVALIDS);
            }
            for (MchAccnt mchAccnt : mchAccntList) {
                String rs = checkMchAccnt(mchAccnt);
                if (StringUtils.isNotEmpty(rs)) {
                    return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, rs);
                }
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }

    /**
     * 子商户账户查询校验
     */
    private Map checkQuery(String data) {
        try {
            MchsubQueryEs card = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), MchsubQueryEs.class);
            if (StringUtils.isEmpty(card.getBizContent().getMchAccntNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{子商户账户号}");
            }
            //账户号必须是已存在的
            MchAccnt mchAccnt = new MchAccnt();
            mchAccnt.setMchAccntNo(card.getBizContent().getMchAccntNo());
            mchAccnt.setMchNo(card.getMchNo());
            if (!checkMchAccntService.getByMchId(mchAccnt)) {
                return createMap(PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULL, PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULLS);
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }

    /**
     * 商户分账校验
     */
    @SuppressWarnings("unchecked")
    private Map checkDispatch(String data) {
        //校验bizContent里的参数
        try {
            String result = StringEscapeUtils.unescapeJava(data);
            DispatchInfo req = JSONObject.parseObject(result, DispatchInfo.class);
            if (ToolUtil.isEmpty(req.getBizContent().get("split_accnt_detail"))) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[split_accnt_detail]参数}");
            }
            List<Accnt> accntList = req.getBizContent().get("split_accnt_detail");//请求业务参数
            Set set = new HashSet();
            List<String> newList = new ArrayList();
            for (Accnt accnt : accntList) {
                if (set.add(accnt.getTransNo())) {
                    newList.add(accnt.getTransNo());
                }
                if (newList.size() > 1) {
                    _log.info("存在不同交易，请检查准确");
                    return createMap(PayConstant.RETURN_DEPOSIT_DISPATCH_DIFTRAN, PayConstant.RETURN_DEPOSIT_DISPATCH_DIFTRANS);
                }
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[split_accnt_detail]参数}");
        }
        return createMap("0000", "");
    }

    /**
     * 商户支付记账校验
     * @param data
     * @return
     */
    @SuppressWarnings("unchecked")
    private Map checkPayDispatch(String data) {
        //校验bizContent里的参数
        try {
            String result = StringEscapeUtils.unescapeJava(data);
            DispatchPayInfo req = JSONObject.parseObject(result, DispatchPayInfo.class);
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_no"))){ //交易流水号
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_no]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_channel"))){ //交易所属通道
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_channel]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_time"))){ //交易完成时间
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_time]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_amt"))){ //交易金额
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_amt]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("settle_type"))){ //结算方式
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[settle_type]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("split_accnt_detail"))) { //分账详情列表
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[split_accnt_detail]参数}");
            }
            String chargeRate = (String) req.getBizContent().get("charge_rate");
            if (ToolUtil.isNotEmpty(chargeRate) && (ToolUtil.isNum(chargeRate) || Double.valueOf(chargeRate) > 0.1)) {
                return createMap("手续费费率不合法", PayConstant.RETURN_DEPOSIT_MUST_NULL);
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[商户支付记账]参数}");
        }
        return createMap("0000", "");
    }

    /**
     * 商户退款记账校验
     * @param data
     * @return
     */
    @SuppressWarnings("unchecked")
    private Map checkRefundDispatch(String data) {
        //校验bizContent里的参数
        try {
            String result = StringEscapeUtils.unescapeJava(data);
            DispatchPayInfo req = JSONObject.parseObject(result, DispatchPayInfo.class);
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_no"))) { //支付交易流水号
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_no]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("refund_trans_no"))) { //退款交易流水号
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[refund_trans_no]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_channel"))) { //交易所属通道
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_channel]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_time"))) { //交易完成时间
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_time]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_amt"))) { //交易金额
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_amt]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("settle_type"))) { //结算方式
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[settle_type]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("split_accnt_detail"))) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[split_accnt_detail]参数}");
            }
            String chargeRate = (String) req.getBizContent().get("charge_rate");
            if (ToolUtil.isNotEmpty(chargeRate) && (ToolUtil.isNum(chargeRate) || Double.valueOf(chargeRate) > 0.1)) {
                return createMap("手续费费率不合法", PayConstant.RETURN_DEPOSIT_MUST_NULL);
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[商户退款记账]参数}");
        }
        return createMap("0000", "");
    }

    /**
     * 商户非支付退款类记账校验
     * @param data
     * @return
     */
    @SuppressWarnings("unchecked")
    private Map checkOtherDispatch(String data) {
        //校验bizContent里的参数
        try {
            String result = StringEscapeUtils.unescapeJava(data);
            DispatchPayInfo req = JSONObject.parseObject(result, DispatchPayInfo.class);
            if (ToolUtil.isEmpty(req.getBizContent().get("trans_no"))) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[trans_no]参数}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().get("split_accnt_detail"))) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[split_accnt_detail]参数}");
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{[商户非支付退款类记账]参数}");
        }
        return createMap("0000", "");
    }

    /**
     * 账户提现校验
     */
    private Map checkWithDraw(String data) {
        try {
            String result = StringEscapeUtils.unescapeJava(data);
            Request007 req = JSONObject.parseObject(result, Request007.class);
            if (req == null) {
                return createMap(PayConstant.RETURN_DEPOSIT_PARAMETER_ERROR, PayConstant.RETURN_DEPOSIT_PARAMETER_ERRORS);
            }
            if (ToolUtil.isEmpty(req.getBizContent().getMchAccntNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{账户号}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().getOrderNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{订单号}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().getCardNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行卡号}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().getAmount())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{提现金额}");
            }
            if (!ToolUtil.isNum(req.getBizContent().getAmount())) {//提现金额需要合法
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{提现金额不合法！}");
            }
            BankCard bankCard = null;
            if (ToolUtil.isNotEmpty(req.getBizContent())) {
                bankCard = checkWithDrawService.selectBankCardInfo(req.getBizContent().getCardNo(), req.getBizContent().getMchAccntNo(), req.getMchNo());
            }

            if (req.getBizContent().getAmount() > 5000000 && ToolUtil.isEmpty(req.getBizContent().getBsbankNo()) && "0".equals(bankCard.getCardAccntType())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{大小额行号}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().getNotifyUrl())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{异步回调地址}");
            }
            if (ToolUtil.isEmpty(req.getBizContent().getType())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{代付类型}");
            }
            //代付类型不在接口范围
            if (!checkWithdrawType(req.getBizContent().getType())) {
                return createMap(PayConstant.RETURN_DEPOSIT_WITHDRAWTYPE_ERROR, PayConstant.RETURN_DEPOSIT_WITHDRAWTYPE_ERRORS);
            }
            //如果是超级网银，则限额五万
            if (PayConstant.DEPOSIT_WITHDRAWTYPE_SUPER.equals(req.getBizContent().getType()) && req.getBizContent().getAmount() > 5000000) {
                return createMap(PayConstant.RETURN_DEPOSIT_SUPER_LIMIT, PayConstant.RETURN_DEPOSIT_SUPER_LIMITS);
            }

            //账户号必须是已存在的
            MchAccnt mchAccnt = new MchAccnt();
            mchAccnt.setMchAccntNo(req.getBizContent().getMchAccntNo());
            mchAccnt.setMchNo(req.getMchNo());
            if (!checkMchAccntService.getByMchId(mchAccnt)) {
                return createMap(PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULL, PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULLS);
            }
            //银行卡号必须是认证成功的
            boolean flag = checkWithDrawService.checkCardNo(req.getBizContent().getCardNo(), req.getBizContent().getMchAccntNo(), req.getMchNo());
            if (!flag) {
                return createMap(PayConstant.RETURN_DEPOSIT_CARD_NULL, PayConstant.RETURN_DEPOSIT_CARD_NULLS);
            }
        } catch (Exception e) {
            _log.info(ToolUtil.getExceptionMsg(e));
            return createMap(PayConstant.RETURN_DEPOSIT_PARAMETER_ERROR, "参数解析参数出错");
        }
        return createMap("0000", "");
    }


    private boolean checkWithdrawType(String type) {
        for (String str : PayConstant.withdrawTypes) {
            if (str.equals(type)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 账户提现查询校验
     */
    private Map checkWithDrawQuery(String data) {
        try {
            PresentQueryEs presentQueryEs = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), PresentQueryEs.class);
            if (StringUtils.isEmpty(presentQueryEs.getBizContent().getMchAccntNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{账户号}");
            }
            if (StringUtils.isEmpty(presentQueryEs.getBizContent().getOrderNo())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{订单号}");
            }
            if (StringUtils.isEmpty(presentQueryEs.getBizContent().getChannel())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{查询渠道}");
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }


    /**
     * 余额查询校验
     */
    private Map checkBalanceQuery(String data) {
        try {
            BalanceQueryEs balanceQueryEs = JSONObject.parseObject(StringEscapeUtils.unescapeJava(data), BalanceQueryEs.class);
            if (StringUtils.isEmpty(balanceQueryEs.getBizContent().getAcctid())) {
                return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{查询账号}");
            }
        } catch (Exception e) {
            return createMap(PayConstant.RETURN_DEPOSIT_CODE_ERROR, PayConstant.RETURN_DEPOSIT_CODES_ERROR);
        }
        //校验bizContent里的参数
        return createMap("0000", "");
    }


    /**
     * param
     * Description: 批量开设子商户效验参数
     * author wzc
     * date 2018/7/24 17:02
     */
    private String checkMchAccnt(MchAccnt mchAccnt) {
        String msg = "";
        if (StringUtils.isEmpty(mchAccnt.getOutMchAccntNo())) {
            msg = "商户系统内部子商户账户号不能为空";
            return msg;
        }
        List<BankCard> bankCardList = mchAccnt.getBank_cards();
        for (BankCard bankCard : bankCardList) {
            msg = checkBandCard(bankCard);
            if (StringUtils.isNotEmpty(msg)) {
                return msg;
            }
        }
        return msg;
    }


    /**
     * 效验参数
     *
     * param
     * return
     */
    private String checkBandCard(BankCard bankCard) {
        String cardAccntType = bankCard.getCardAccntType();
        String msg = "";


        //绑卡公共参数
        if (ToolUtil.isEmpty(bankCard.getMchAccntNo())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{子商户账号}";
            return msg;
        }
        if (ToolUtil.isEmpty(cardAccntType)) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行卡账户类型}";
            return msg;
        }
        if (ToolUtil.isEmpty(bankCard.getOrderNo())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{订单号}";
            return msg;
        }
        if (!"1".equals(cardAccntType) && !"0".equals(cardAccntType)) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行卡账户类型无效}";
            return msg;
        }
        if (StringUtils.isEmpty(bankCard.getCardNo())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行卡号}";
            return msg;
        }
        if (StringUtils.isEmpty(bankCard.getBankName())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{开户行名称}";
            return msg;
        }
        /*if (StringUtils.isEmpty(bankCard.getBankBranchName( ))) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS+":{分支行信息}";
            return msg;
        }
        if (bankCard.getBankBranchName().length()<2) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS+":{分支行信息不合法}";
            return msg;
        }*/
        if (StringUtils.isEmpty(bankCard.getUserName())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{户名}";
            return msg;
        }

        if (StringUtils.isEmpty(bankCard.getCardPhone())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行预留手机号码}";
            return msg;
        }
        if (StringUtils.isEmpty(bankCard.getNotifyUrl())) {
            msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{异步通知地址}";
            return msg;
        }



        //分对公、对私校验
        if ("1".equals(cardAccntType)) {//对私

            if (StringUtils.isEmpty(bankCard.getCertType())) {
                msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{证件类型}";
                return msg;
            }
            if (StringUtils.isEmpty(bankCard.getCertNo())) {
                msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{持有人证件号}";
                return msg;
            }
            if (StringUtils.isEmpty(bankCard.getCardType())) {
                msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行卡类型}";
                return msg;

            }
            if (StringUtils.isEmpty(bankCard.getBankNo())) {
                msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{银行代码}";
                return msg;
            }
            if (!"0".equals(bankCard.getCertType())) {
                msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{目前仅支持身份证}";
                return msg;
            }
            if ("1".equals(bankCard.getCardType())) {
                if (StringUtils.isEmpty(bankCard.getCardCvn())) {
                    msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{信用卡cvn}";
                    return msg;
                }
                if (null == bankCard.getCardExpireDate()) {
                    msg = PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{信用卡有效期}";
                    return msg;
                }
            }

        }

        return msg;
    }

    /**
     * 往账接口校验
     */
    private Map checkNostro(String data) {
        //校验bizContent里的参数
        Nostro req = JSONObject.parseObject(data, Nostro.class);
        //外部子商户号不合法
        String amt = req.getBizContent().getAmt();
        String mchNo = req.getMchNo();
        String mchAccntNo = req.getBizContent().getMchAccntNo();
        String cardNo = req.getBizContent().getCardNo();
        if (ToolUtil.isEmpty(amt)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{往账金额}");
        }
        if (ToolUtil.isEmpty(mchAccntNo)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{账户号}");
        }
        if (ToolUtil.isEmpty(cardNo)) {
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{卡号}");
        }
        MchAccnt mchAccnt = new MchAccnt();
        mchAccnt.setMchAccntNo(mchAccntNo);
        mchAccnt.setMchNo(mchNo);
        if (!checkMchAccntService.getByMchId(mchAccnt)) {//账户一定要存在
            return createMap(PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULL, PayConstant.RETURN_DEPOSIT_MCHSUBNO_NULLS);
        }
        if (!ToolUtil.isNum(amt)) {//往账金额需合法
            return createMap(PayConstant.RETURN_DEPOSIT_MUST_NULL, PayConstant.RETURN_DEPOSIT_MUST_NULLS + ":{往账金额不合法！}");
        }
        BankCard bankCard = checkWithDrawService.checkNostro(cardNo, mchAccntNo, mchNo, "0");
        if (ToolUtil.isEmpty(bankCard)) {//卡号需已存在
            return createMap(PayConstant.RETURN_DEPOSIT_CARD_NULL, PayConstant.RETURN_DEPOSIT_CARD_NULLS);
        }
        if (!"0".equals(bankCard.getCardAccntType())) {
            return createMap(PayConstant.RETURN_DEPOSIT_ACCNTTYPE_ERROR, PayConstant.RETURN_DEPOSIT_ACCNTTYPE_ERRORS);
        }
        return createMap("0000", "");
    }
}
